package fm.realm;

import com.alibaba.fastjson.JSON;
import fm.dto.AdminUser;
import fm.dto.NeiyiUser;
import fm.mongoService.UserService;
import fm.mongoService.TokenService;
import fm.sys.token.Token;
import fm.web.CurrentRequest;
import fm.cache.RoleCache;
import fm.exception.BizException;
import fm.sys.token.AdminToken;
import fm.sys.token.MerchantToken;
import fm.util.Constant;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.security.auth.login.LoginException;
import java.util.ArrayList;
import java.util.List;

/**
 * 类名： fm.realm.UserRealm
 * 创建人： CM
 * 创建时间： 2016/3/6.
 */
public class UserRealm extends AuthorizingRealm {

    private static Logger LOGGER = LoggerFactory.getLogger(UserRealm.class);

    @Autowired
    UserService userService;
    @Autowired
    TokenService tokenService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String phone = (String) principals.getPrimaryPrincipal();

        List<String> roles = new ArrayList<>();

        if (principals.getRealmNames().contains("ADMIN")) {
            roles.addAll(RoleCache.getPermision("ADMIN"));

        } else if (principals.getRealmNames().contains("MERCHANT")) {
            try {

                NeiyiUser user = (NeiyiUser) CurrentRequest.getCurrentUser();
                Integer userType = user.getUserType();
                if (userType > 1) {
                    String key = "MERCHANT" + userType;

                    List<String> userRoles = RoleCache.getPermision(key);
                    roles.addAll(userRoles);
                }

            } catch (Exception e) {
                LOGGER.error("获取用户信息失败，无法授权！", e);
            }
        }else {
            LOGGER.warn("未定义的用户类型，无法获取相关权限角色:{}",principals.getRealmNames());
        }

        LOGGER.info("authorization finnish:{} ,user roles : {}", principals.getPrimaryPrincipal(), JSON.toJSONString(roles));

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles(roles);
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        try {

            SimpleAuthenticationInfo info = null;

            if (token instanceof AdminToken) {
                AdminToken adminToken = (AdminToken) token;

                if (!userService.checkPass(adminToken.getPrincipal().toString(), adminToken.getCredentials().toString())) {
                    throw new UnknownAccountException("invalid account/password!");
                }
                AdminUser user = new AdminUser();
                SecurityUtils.getSubject().getSession().setAttribute(Constant.SESSION_LOGIN_USER, user);
                info = new SimpleAuthenticationInfo(adminToken.getPrincipal(), adminToken.getCredentials(), "ADMIN");

            } else if (token instanceof MerchantToken) {
                MerchantToken merchantToken = (MerchantToken) token;
                NeiyiUser user;
                if (StringUtils.isNotEmpty(merchantToken.getToken())) {
                    Token ticket = tokenService.undecodeToken(merchantToken.getToken());
                    if (ticket.isExpired()) {
                        throw new LoginException("身份验证已经过期,请尝试重新登陆!");
                    }
                    String userId = ticket.getKey();
                    user = userService.getById(userId);
                } else if (userService.checkSms(merchantToken.getPrincipal().toString(), merchantToken.getCredentials().toString())) {
                    user = userService.getUserByPhone(token.getPrincipal().toString());
                } else {
                    throw new UnknownAccountException("authenticate failed!");
                }
                SecurityUtils.getSubject().getSession().setAttribute(Constant.SESSION_LOGIN_USER, user);

                info = new SimpleAuthenticationInfo(merchantToken.getPrincipal(), merchantToken.getCredentials(), "MERCHANT");

            }else{
                LOGGER.warn("未定义的授权类型，无法构建认证信息:{}",JSON.toJSONString(token));
            }

            return info;
        } catch (UnknownAccountException ex) {
            throw ex;
        } catch (BizException ex) {
            throw new UnknownAccountException(ex.getMessage());
        } catch (Exception ex) {
            LOGGER.error("安全校验发生错误：", ex);
            throw new RuntimeException("account check error!");
        }

    }


    @Override
    public boolean supports(AuthenticationToken token) {
        if (token instanceof AdminToken || token instanceof MerchantToken) {
            return true;
        } else {
            return super.supports(token);
        }
    }


}
